<?php

namespace Swostar\Server\WebSocket;

use Exception;
use Swostar\Rpc\Rpc;
use Swoole\Http\Request;
use Swoole\Http\Response;
use Swostar\Server\Http\HttpServer;
use Swoole\WebSocket\Server as SwooleServer;

class WebSocketServer extends HttpServer
{

    public function start()
    {
        // 设置多端口监听
        // $config = app('config');
        // if ($config->get('server.websocket.rpcOnOff')) {
        //     new Rpc($this->swooleServer, $config->get('server.websocket.rpc'));
        // }


        // $tcp_server = $this->swooleServer->addListener('0.0.0.0', 9999, SWOOLE_SOCK_TCP);
        
      
        // $tcp_server->on('message', [$this, 'aaa']);
        // $tcp_server->on('close', [$this, 'bbb']);


        // 服务启动
        $this->swooleServer->start();
    }

    public function aaa(SwooleServer $server, $frame)
    {
        echo 'aaa' . PHP_EOL;

        $data = json_decode($frame->data, true);

        $server->push($data['fd'], json_encode(['msg' => $data['msg']]));
    }

    public function bbb($server, $fd)
    {
    }


    public function createServer()
    {
        $this->swooleServer = new SwooleServer($this->host, $this->port);

        echo "websocket server start {$this->host}:{$this->port}" . PHP_EOL;
    }

    protected function initEvents() {
        $events = [
            'request' => 'onRequest',
            'open'    => 'onOpen',
            'message' => 'onMessage',
            'close'   => 'onClose',
        ];

        // 若设置了握手回调
        if (app('config')->get('server.websocket.handShakeOnOff')) {
            $events['handShake'] = 'onHandShake';
        }
        
        $this->setEvent('sub', $events);
    }

    /**
     * 自定义握手回调
     * @param Request $request 
     * @param Response $response 
     * @return void 
     */
    public function onHandShake(Request $request, Response $response)
    {
        app('event')->trigger('ws.handShake', [$this, $request, $response]);

        // 因为设置onHandShake回调后，不会触发onOpen回调，所以需要调用
        $this->onOpen($this->swooleServer, $request);
    }

    // 设置 onHandShake 回调函数后不会再触发 onOpen 事件，需要应用代码自行处理
    public function onOpen(SwooleServer $server = null, $request = null)
    {
        Connections::init($request->fd, $request);

        // 路由解析
        app('route')->setModule('websocket')->match('open', $request->server['path_info'], [$server, $request]);
    }

    public function onMessage(SwooleServer $server, $frame)
    {
        $path = Connections::get($frame->fd)['path'];

        // 事件监听--判定消息发送类型为单聊，群聊
        app('event')->trigger('ws.message.before', [$this, $server, $frame]);

        // 业务逻辑执行
        app('route')->setModule('websocket')->match('message', $path, [$server, $frame]);

        // 有可能有后置事件
    }

    public function onClose($server, $fd)
    {

        echo '关闭事件触发'. PHP_EOL;
        echo "<pre>";
        print_r(Connections::get());
        echo "</pre>";
        echo PHP_EOL;
        

        $path = Connections::get($fd)['path'];

        // 路由解析
        app('route')->setModule('websocket')->match('close', $path, [$server, $fd]);

        // 事件监听
        app('event')->trigger('ws.close', [$this, $server, $fd]);


        Connections::delete($fd);
    }

    /**
     * 群聊发送
     * @param mixed|null $groupId 
     * @param mixed $msg 
     * @return void 
     */
    public function sendGroup($groupId = null, $msg)
    {
        // 若群id不存在，获取群成员
        if (!$groupId) {
            $connections = $this->swooleServer->connections;
        }
        // 群id存在逻辑
        // ....

        // 循环发送
        foreach ($connections as $fd) {
            if ($this->swooleServer->exist($fd)) {
                $this->swooleServer->push($fd, $msg);
            }
        }
    }
}
